package com.whmskj.xjlhsc.mobie.energymanage.service.impl;

import com.whmskj.xjlhsc.mobie.energymanage.mapper.MobileEnergyDayMapper;
import com.whmskj.xjlhsc.mobie.energymanage.mapper.MobileEquipmentMapper;
import com.whmskj.xjlhsc.mobie.energymanage.service.MobileEnergyService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class MobileEnergyServiceImpl implements MobileEnergyService {
    @Resource private MobileEnergyDayMapper energyDayMapper;
    @Resource private MobileEquipmentMapper mobileEquipmentMapper;

    @Override
	public List<Map<String, Object>> overview(LocalDate day, String process) {
        if (day == null) day = LocalDate.now();
		List<Map<String, Object>> result = energyDayMapper.overview(day, process);
		// 格式化所有数值为两位小数
		result.forEach(this::formatNumbers);
        return result;
    }

    @Override
    public Map<String, Object> deviceDetail(Long deviceId) {
        LocalDate now = LocalDate.now();
        YearMonth ym = YearMonth.from(now);
        Map<String,Object> detail = new LinkedHashMap<>();
        
        // 获取设备电能数据汇总（仅用于计算todayKwh，不返回该节点）
        Map<String, Object> energySummary = energyDayMapper.getDeviceEnergySummary(deviceId);
        
        // 获取最新实时电参（经 relations 映射）
        Map<String, Object> realtime = energyDayMapper.latestRealtimeByDeviceId(deviceId);
        if (realtime == null) realtime = new LinkedHashMap<>();

        // 最近7天能耗（含今天）
        LocalDate start7 = now.minusDays(6);
        List<Map<String,Object>> last7Days = energyDayMapper.seriesByMesid(deviceId, start7, now);
        double total7 = 0D;
        if (last7Days != null) {
            for (Map<String,Object> row : last7Days) {
                Object v = row.get("kwh");
                if (v instanceof Number) total7 += ((Number) v).doubleValue();
                else if (v != null) {
                    try { total7 += new java.math.BigDecimal(String.valueOf(v)).doubleValue(); } catch (Exception ignored) {}
                }
            }
        }
        // 今日能耗
        List<Map<String,Object>> todayList = energyDayMapper.seriesByMesid(deviceId, now, now);
        double todayKwh = 0D;
        if (todayList != null && !todayList.isEmpty()) {
            todayKwh = getNumber(todayList.get(0), "kwh");
        }
        if (todayKwh == 0D) {
            // 兜底：从汇总中取 todayKwh
            todayKwh = getNumber(energySummary, "todayKwh");
        }
        double totalAll = getNumber(energySummary, "totalKwh");
        // 写入到 realtime
        realtime.put("todayKwh", Math.round(todayKwh * 100.0) / 100.0);
        realtime.put("totalKwh", Math.round(totalAll * 100.0) / 100.0); // 累计总能耗（所有天）
        realtime.put("last7Days", last7Days == null ? java.util.Collections.emptyList() : last7Days);

        detail.put("realtime", realtime);

        // 数值格式化
        formatNumbers(detail);
        return detail;
    }

	@Override
	public List<String> processes() {
		return mobileEquipmentMapper.listProcesses();
	}
	

	@Override
	public List<Map<String, Object>> getCollectionStatusStats(String process) {
		List<Map<String,Object>> rows = energyDayMapper.countCollectionStatus(process, null);
		List<Map<String,Object>> result = new java.util.ArrayList<>();
		
		if (rows != null) {
			for (Map<String,Object> r : rows) {
				Object f = r.get("collectFlag");
				Object c = r.get("count");
				int flag = (f instanceof Number) ? ((Number)f).intValue()
						: (f != null ? Integer.parseInt(String.valueOf(f)) : 0);
				long cnt = (c instanceof Number) ? ((Number)c).longValue()
						: (c != null ? Long.parseLong(String.valueOf(c)) : 0L);
				
				Map<String,Object> item = new LinkedHashMap<>();
				item.put("collectFlag", flag);
				item.put("count", cnt);
				result.add(item);
			}
		}

		boolean hasNormal = result.stream().anyMatch(item -> Integer.valueOf(1).equals(item.get("collectFlag")));
		boolean hasInterrupted = result.stream().anyMatch(item -> Integer.valueOf(0).equals(item.get("collectFlag")));
		
		if (!hasNormal) {
			Map<String,Object> normalItem = new LinkedHashMap<>();
			normalItem.put("collectFlag", 1);
			normalItem.put("count", 0L);
			result.add(normalItem);
		}
		if (!hasInterrupted) {
			Map<String,Object> interruptedItem = new LinkedHashMap<>();
			interruptedItem.put("collectFlag", 0);
			interruptedItem.put("count", 0L);
			result.add(interruptedItem);
		}
		
		return result;
	}

	@Override
	public List<Map<String, Object>> getCollectionStatusStats() {
		return getCollectionStatusStats(null);
	}

	/**
	 * 从Map安全读取数值，null/不可解析时返回0
	 */
	private double getNumber(Map<String, Object> map, String key) {
		if (map == null) return 0D;
		Object v = map.get(key);
		if (v == null) return 0D;
		if (v instanceof Number) {
			return ((Number) v).doubleValue();
		}
		if (v instanceof String) {
			String s = ((String) v).trim();
			if (s.isEmpty()) return 0D;
			try {
				return new java.math.BigDecimal(s).doubleValue();
			} catch (Exception ignored) {
				return 0D;
			}
		}
		return 0D;
	}

	/**
	 * 格式化Map中的所有数值为两位小数
	 */
	private void formatNumbers(Map<String, Object> data) {
		if (data == null) return;
		
		data.forEach((key, value) -> {
			if (value instanceof Number) {
				// 数值类型保留两位小数
				if (value instanceof Double || value instanceof Float) {
					data.put(key, Math.round(((Number) value).doubleValue() * 100.0) / 100.0);
				} else if (value instanceof BigDecimal) {
					data.put(key, ((BigDecimal) value).setScale(2, RoundingMode.HALF_UP));
				}
			} else if (value instanceof Map) {
				// 递归处理嵌套的Map（如realtime数据）
				formatNumbers((Map<String, Object>) value);
			}
		});
	}

    private static Map<Object, Map<String,Object>> indexBy(List<Map<String,Object>> list, String key) {
        return list == null ? Collections.emptyMap() : list.stream().filter(Objects::nonNull).collect(Collectors.toMap(m -> m.get(key), Function.identity(), (a,b)->a, LinkedHashMap::new));
    }
    private static Object getOrNull(Map<Object, Map<String,Object>> map, Object key, String valueKey) {
        Map<String,Object> v = map.get(key);
        return v == null ? null : v.get(valueKey);
    }
}
